from tortoise.expressions import Q
from app.controllers.jobs.jobs_log import jobs_log_controller
from app.core.crud import CRUDBase
from app.models.jobs import JobsRule
from app.schemas.jobs import JobsRuleCreate, JobsRuleUpdate, JobsLogCreate
from app.utils.TaskScheduler import TaskScheduler
import httpx
import json

scheduler = TaskScheduler()


class JobsRuleController(CRUDBase[JobsRule, JobsRuleCreate, JobsRuleUpdate]):
    def __init__(self):
        super().__init__(model=JobsRule)

    async def do_list(self, page: int, page_size: int, search: Q = Q()):
        jobs = scheduler.get_jobs()
        await JobsRule.filter(~Q(id__in=jobs)).update(state=False)
        await JobsRule.filter(id__in=jobs).update(state=True)
        query = self.model.filter(search)
        total = await query.count()
        objs = await query.offset((page - 1) * page_size).limit(page_size).order_by('-id')
        data = [await obj.to_dict() for obj in objs]

        return total, data

    async def do_detail(self, data_id: int):
        obj = await self.get(id=data_id)
        data = await obj.to_dict()
        return data

    async def do_create(self, obj_in: JobsRuleCreate):
        await self.create(obj_in=obj_in)
        return True

    async def do_update(self, obj_in: JobsRuleUpdate):
        scheduler.stop_job(job_id=f"my_job{obj_in.id}")
        await self.update(id=obj_in.id, obj_in=obj_in)
        job_id = obj_in.id
        url = obj_in.func_name
        if obj_in.state:
            if obj_in.type == 1:
                cron_expr = {}
            else:
                if obj_in.day == 0:
                    day = None
                else:
                    day = obj_in.day
                cron_expr = {
                    'day': day,
                    'hour': obj_in.hour,
                    'minute': obj_in.minute,
                    'second': obj_in.second
                }
            scheduler.start_job(f"my_job{job_id}", obj_in.times, cron_expr, self.my_async_task, job_id, url)
        else:
            scheduler.stop_job(job_id=f"my_job{job_id}")
        return True

    ##自启动
    async def up_all(self):
        jobs = await JobsRule.filter(up_type=1).all()
        for obj_in in jobs:
            if obj_in.day == 0:
                day = None
            else:
                day = obj_in.day
            cron_expr = {
                'day': day,
                'hour': obj_in.hour,
                'minute': obj_in.minute,
                'second': obj_in.second
            }
            scheduler.start_job(f"my_job{obj_in.id}", obj_in.times, cron_expr, self.my_async_task, obj_in.id,
                                obj_in.func_name)

    @staticmethod
    async def my_async_task(job_id, url):
        url = url
        token = "dev"
        headers = {
            "Authorization": f"Bearer {token}",
            "Token": token
        }
        async with httpx.AsyncClient() as client:
            response = await client.get(url, headers=headers)

        if response.status_code == 200:
            data = response.json()
            result_status = 1
            result_data = json.dumps(data, ensure_ascii=False, indent=4)
        else:
            result_status = 2
            result_data = response.status_code

        jobs_log_data = {
            "user_id": 0,
            "job_id": job_id,
            "result_status": result_status,
            "result_data": result_data,
        }
        jobs_log_data_in = JobsLogCreate(**jobs_log_data)
        await jobs_log_controller.do_create(jobs_log_data_in)

    async def do_delete(self, data_id: int):
        await self.remove(id=data_id)
        scheduler.stop_job(job_id=f"my_job{data_id}")
        return True

    async def level_list(self):
        objs = await self.model.all().values("id", "name")
        data = dict()
        for obj in objs:
            data[obj['id']] = obj['name']
        return data


jobs_rule_controller = JobsRuleController()
